﻿using System;
using System.Collections;
using System.Configuration;
using System.Data;

using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

using SaleManagement.Web.App_Code;
using SaleManagement.Domains;
using SaleManagement.Services;
using DevExpress.Web.ASPxGridView;
using System.Text;
using System.Transactions;

namespace SaleManagement.Web.Pages
{
  public partial class PurchaseInfo : BasePage
  {
    #region Variables and properties
    private string _cbxProductInnerError = string.Empty;
    private string _gvPurchaseDetailInnerError = string.Empty;

    private DataTable PurchaseDetailTable
    {
      get
      {
        if (Session["PurchaseDetailTable"] == null)
        {
          DataTable dt = new DataTable();
          Session["PurchaseDetailTable"] = dt;
        }
        return Session["PurchaseDetailTable"] as DataTable;
      }

      set
      {
        Session["PurchaseDetailTable"] = value;
      }
    }

    private int DetailId
    {
      get
      {
        if (Session["PurchaseDetailId"] == null)
        {
          Session["PurchaseDetailId"] = 0;
        }

        return Convert.ToInt32(Session["PurchaseDetailId"]);
      }

      set
      {
        Session["PurchaseDetailId"] = value;
      }
    }
    #endregion

    #region Events
    protected void Page_Load(object sender, EventArgs e)
    {
      if (!IsPostBack && !IsCallback)
      {
        if (!string.IsNullOrEmpty(Request.QueryString["id"]))
        {
          hfPurchaseId.Value = Request.QueryString["id"];
          trChangeReason.Visible = true;
        }
        else
        {
          trChangeReason.Visible = false;
          btnApprove.ClientVisible = false;
          btnReject.ClientVisible = false;
        }

        LoadCommonInfo();
        LoadPurchaseDetailList();
      }
    }

    protected void cbxProduct_Callback(object source, DevExpress.Web.ASPxClasses.CallbackEventArgsBase e)
    {
      int groupId = Convert.ToInt32(cbxProductGroup.Value);
      ProductGroup group = new ProductGroupService().GetById(groupId);
      if (group != null)
      {
        _cbxProductInnerError = group.IsInventory ? "IsInventory" : "IsNotInventory";
        cbxProduct.DataSource = new ProductService().GetByGroupId(groupId);
        cbxProduct.DataBind();
      }
    }

    protected void cbxProduct_CustomJSProperties(object sender, DevExpress.Web.ASPxClasses.CustomJSPropertiesEventArgs e)
    {
      e.Properties["cpInnerError"] = _cbxProductInnerError;
    }

    protected void cbPurchase_Callback(object source, DevExpress.Web.ASPxCallback.CallbackEventArgs e)
    {
      int productId = Convert.ToInt32(cbxProduct.Value);
      TList<Price> priceList = new PriceService().GetTopByProductId(productId);
      if (priceList.Count > 0)
      {
        e.Result = priceList[0].Price.ToString();
      }
    }

    protected void gvPurchaseDetail_CustomCallback(object sender, ASPxGridViewCustomCallbackEventArgs e)
    {
      string[] para = e.Parameters.Split('|');
      switch (para[0])
      {
        case "DeleteDetail":
          _gvPurchaseDetailInnerError = DeletePurchaseDetail(Convert.ToInt32(para[1]));
          break;
        case "SaveDetail":
          _gvPurchaseDetailInnerError = SavePurchaseDetail();
          break;
        case "Save":
          _gvPurchaseDetailInnerError = Save();
          break;
        case "Approve":
          _gvPurchaseDetailInnerError = Approve();
          break;
        case "Reject":
          _gvPurchaseDetailInnerError = Reject();
          break;
        default:
          break;
      }

      LoadPurchaseDetailList();
    }

    protected void gvPurchaseDetail_CustomJSProperties(object sender, ASPxGridViewClientJSPropertiesEventArgs e)
    {
      e.Properties["cpInnerError"] = _gvPurchaseDetailInnerError;
    }

    protected void gvCustomer_CustomCallback(object sender, DevExpress.Web.ASPxGridView.ASPxGridViewCustomCallbackEventArgs e)
    {
      LoadCustomerList();
    }

    protected void gvCustomer_PageIndexChanged(object sender, EventArgs e)
    {
      LoadCustomerList();
    }
    #endregion

    #region Methods
    private void LoadCommonInfo()
    {
      int purchaseId = 0;
      if (int.TryParse(hfPurchaseId.Value, out purchaseId))
      {
        Purchase purchase = new PurchaseService().GetById(purchaseId);
        if (purchase != null)
        {
          if (purchase.Status == StatusList.PurchaseStatus.WaitingToApprove)
          {
            btnReject.ClientVisible = true;
            btnApprove.ClientVisible = true;
          }

          #region Purchase
          txtPurchaseCode.Text = purchase.RefNo;
          dePurchaseDate.Date = purchase.Date;
          if (purchase.Total.HasValue)
          {
            txtTotalMoney.Text = purchase.Total.Value.ToString();
          }

          if (purchase.Commission.HasValue)
          {
            txtCommission.Text = purchase.Commission.Value.ToString();
          }

          cbxRepository.Value = purchase.RepositoryId;
          mmPurchaseNotes.Text = purchase.Notes;
          mmChangeReason.Text = purchase.RequiredModified;

          #endregion

          #region Payment
          TList<Domains.PaymentDetail> paymentList = new PaymentDetailService().GetByPurchaseId(purchaseId);
          if (paymentList.Count > 0)
          {
						txtPrepaid.Value = paymentList[0].Amount;
            txtPrepaid.ClientEnabled = false;
          }
          #endregion

          #region Customer
          hfCustomerId.Value = purchase.CustomerId.ToString();
          Customer customer = new CustomerService().GetById(purchase.CustomerId);
          if (customer != null)
          {
            txtCustomerName.Text = customer.Name;
            btneCustomerNo.Text = customer.CustomerNo;
            txtCustomerPhone.Text = customer.Phone;
            txtCustomerEmail.Text = customer.Email;
            txtCustomerFax.Text = customer.Fax;
            txtCustomerAddress.Text = customer.Address;
          }
          #endregion
        }
      }

      #region PurchaseDetail
      DataSet ds = new PurchaseDetailService().SearchByPurchaseId(purchaseId);
      if (ds != null && ds.Tables.Count > 0)
      {
        PurchaseDetailTable = ds.Tables[0];
        PurchaseDetailTable.PrimaryKey = new DataColumn[] { PurchaseDetailTable.Columns["Id"] };
        PurchaseDetailTable.Columns.Add("Deleted", typeof(bool));
      }
      #endregion

      #region Combobox
      cbxProductGroup.DataSource = new ProductGroupService().GetAll();
      cbxProductGroup.DataBind();

      cbxRepository.DataSource = new RepositoryService().Search(StatusList.RepositoryType.PRODUCT);
      cbxRepository.DataBind();
      #endregion
    }

    private void LoadCustomerList()
    {
      string customerCode = null;
      string customerName = null;
      string phone = null;
      if (!string.IsNullOrEmpty(txtSearchCode.Text.Trim()))
      {
        customerCode = txtSearchCode.Text.Trim();
      }

      if (!string.IsNullOrEmpty(txtSearchName.Text.Trim()))
      {
        customerName = txtSearchName.Text.Trim();
      }

      if (!string.IsNullOrEmpty(txtSearchPhone.Text.Trim()))
      {
        phone = txtSearchPhone.Text.Trim();
      }

      TList<Customer> ds = new CustomerService().Search(customerCode, customerName, phone);
      gvCustomer.DataSource = ds;
      gvCustomer.DataBind();

    }

    private void LoadPurchaseDetailList()
    {
      gvPurchaseDetail.DataSource = PurchaseDetailTable;
      gvPurchaseDetail.FilterExpression = "Deleted <> true";
      gvPurchaseDetail.DataBind();
    }

    private string SavePurchaseDetail()
    {
      PurchaseDetailService service = new PurchaseDetailService();

      #region Check parameters
      if (!string.IsNullOrEmpty(hfDetailCode.Value))
      {
        string[] codeList = hfDetailCode.Value.Split(',');
        foreach (string code in codeList)
        {
        
          TList<PurchaseDetail> detailList = service.GetByCode(code.ToUpper());
          if (detailList.Count <= 0)
          {
            if (PurchaseDetailTable.Select("Code = '" + code.ToUpper() + "'").Length <= 0)
            {
              continue;
            }
          }

          return "Mã sản phẩm '" + code + "' đã tồn tại, yêu cầu chọn mã khác.";
        }
      }

      int repositoryId = Convert.ToInt32(cbxRepository.Value);
      int productId = Convert.ToInt32(cbxProduct.Value);
      double quantity = Convert.ToDouble(txtDetailQuantity.Text);
      foreach (DataRow row in PurchaseDetailTable.Select("Deleted <> 1"))
      {
        if (Convert.ToInt32(row["Id"]) <= 0 && Convert.ToInt32(row["ProductId"]) == productId)
        {
          quantity += Convert.ToDouble(row["Quantity"]);
        }
      }
      Product product = new ProductService().GetById(productId);
      ProductGroup group = new ProductGroupService().GetById(product.Id);
      if (group != null && group.IsInventory)
      {
        TList<StoredProduct> sProductList = new StoredProductService().GetByRepositoryIdProductId(repositoryId, productId);
        if (sProductList.Count <= 0)
        {
          return "Sản phẩm này hiện chưa được nhập kho";
        }
        else if (sProductList.Count > 0 && sProductList[0].CurrentQuantity < quantity)
        {
          return "Số lượng sản phẩm yêu cầu vượt quá số lượng hiện có (" + sProductList[0].CurrentQuantity.ToString() + ").";
        }
      }
      #endregion

      #region Save to term table
      try
      {
        int detailId;
        if (!string.IsNullOrEmpty(hfDetailCode.Value))
        {
          string[] codeList = hfDetailCode.Value.Split(',');
          foreach (string code in codeList)
          {
            DataRow row = null;
            if (int.TryParse(hfDetailId.Value, out detailId))
            {
              row = PurchaseDetailTable.Rows.Find(detailId);
            }

            if (row == null)
            {
              row = PurchaseDetailTable.NewRow();
              row["Id"] = DetailId;
              DetailId -= 1;
              PurchaseDetailTable.Rows.Add(row);
            }

            row["Code"] = code.ToUpper();
            row["ProductGroupId"] = Convert.ToInt32(cbxProductGroup.Value);
            row["ProductGroupName"] = cbxProductGroup.Text;
            row["ProductId"] = productId;
            row["ProductName"] = cbxProduct.Text;
            row["Quantity"] = 1;
            row["Price"] = Convert.ToInt32(txtDetailPrice.Text);
            row["Deleted"] = false;
          }
        }
        else
        {
          DataRow row = null;
          if (int.TryParse(hfDetailId.Value, out detailId))
          {
            row = PurchaseDetailTable.Rows.Find(detailId);
          }

          if (row == null)
          {
            row = PurchaseDetailTable.NewRow();
            row["Id"] = DetailId;
            DetailId -= 1;
            PurchaseDetailTable.Rows.Add(row);
          }

          row["ProductGroupId"] = Convert.ToInt32(cbxProductGroup.Value);
          row["ProductGroupName"] = cbxProductGroup.Text;
          row["ProductId"] = productId;
          row["ProductName"] = cbxProduct.Text;
          row["Quantity"] = Convert.ToDouble(txtDetailQuantity.Text);
          row["Price"] = Convert.ToInt32(txtDetailPrice.Text);
          row["Deleted"] = false;
        }

        return "SaveDetail";
      }
      catch (Exception ex)
      {
        WriteLog("PurchaseInfo::SavePurchaseDetail", ex);
        return "Có lỗi trong quá trình lưu dữ liệu";
      }
      #endregion
    }

    private string DeletePurchaseDetail(int id)
    {
      try
      {
        DataRow row = PurchaseDetailTable.Rows.Find(id);
        if (row != null)
        {
          row["Deleted"] = true;
        }

        return "DeleteDetail";
      }
      catch (Exception ex)
      {
        WriteLog("PurchaseInfo::DeletePurchaseDetai", ex);
        return "Có lỗi trong quá trình xóa dữ liệu";
      }
    }

    private string Save()
    {
      try
      {
        Customer customer = null;
        Purchase purchase = null;
        CustomerService cusService = new CustomerService();
        PurchaseService purService = new PurchaseService();

        using (ConnectionScope.CreateTransaction())
        {
          int customerId, purchaseId;
          PurchaseDetailService detailService = new PurchaseDetailService();
          ProductService productService = new ProductService();

          #region Customer
          if (int.TryParse(hfCustomerId.Value, out customerId))
          {
            customer = cusService.GetById(customerId);
          }

          if (customer == null)
          {
            customer = new Customer();
          }

          customer.Name = Utilities.SafeString(txtCustomerName.Text);
          customer.Address = Utilities.SafeString(txtCustomerAddress.Text);
          customer.Phone = Utilities.SafeString(txtCustomerPhone.Text); ;
          customer.Fax = Utilities.SafeString(txtCustomerFax.Text);
          customer.Email = Utilities.SafeString(txtCustomerEmail.Text);

          cusService.Save(customer);
          #endregion

          #region Purchase
          if (int.TryParse(hfPurchaseId.Value, out purchaseId))
          {
            purchase = purService.GetById(purchaseId);
          }

          if (purchase == null)
          {
            purchase = new Purchase();
            purchase.CreatedBy = CurrentUser.Username;
            purchase.CreatedDate = DateTime.Now;
            purchase.Status = StatusList.PurchaseStatus.New;
          }
          else
          {
            purchase.Status = StatusList.PurchaseStatus.WaitingToApprove;
            purchase.UpdatedBy = CurrentUser.Username;
            purchase.UpdatedDate = DateTime.Now;
          }

          purchase.CustomerId = customer.Id;
          purchase.Date = dePurchaseDate.Date;
          purchase.RepositoryId = Convert.ToInt32(cbxRepository.Value);
          purchase.Total = Convert.ToInt32(txtTotalMoney.Text);
          purchase.Commission = Convert.ToInt32(txtCommission.Text);
          purchase.RealTotal = purchase.Total - purchase.Commission;
          purchase.Notes = Utilities.SafeString(mmPurchaseNotes.Text);
          purchase.RequiredModified = Utilities.SafeString(mmChangeReason.Text);
          /*
           * Case Insert: auto insert into tblBackupPurchase
           * Case update: Do nothing
           */
          purService.Save(purchase);
          #endregion

          #region Payment
          if (txtPrepaid.ClientEnabled && txtPrepaid.Text != "0")
          {
            Domains.Payment payment = new Payment();
            payment.CustomerId = customer.Id;
            payment.Amount = Convert.ToInt32(txtPrepaid.Text);
            payment.Date = dePurchaseDate.Date;
            payment.UpdatedBy = CurrentUser.Username;
            payment.UpdatedDate = DateTime.Now;
            new PaymentService().Save(payment);

            Domains.PaymentDetail paymentDetail = new Domains.PaymentDetail();
            paymentDetail.PurchaseId = purchase.Id;
            paymentDetail.Amount = Convert.ToInt32(txtPrepaid.Text);
            paymentDetail.Date = dePurchaseDate.Date;
            paymentDetail.Notes = "Tiền trả trước";
            paymentDetail.UpdatedBy = CurrentUser.Username;
            paymentDetail.UpdatedDate = DateTime.Now;
            paymentDetail.PaymentId = payment.Id;

            new PaymentDetailService().Save(paymentDetail);
          }
          #endregion

          #region Detail
          foreach (DataRow row in PurchaseDetailTable.Rows)
          {
            int detailId = Convert.ToInt32(row["Id"]);
            bool deleted = row["Deleted"] == DBNull.Value ? false : Convert.ToBoolean(row["Deleted"]);
            PurchaseDetail detail = null;
            if (detailId > 0)
            {
              detail = detailService.GetById(detailId);
            }

            if (deleted)
            {
              #region Delete
              if (detail != null)
              {
                detailService.Delete(detail);
              }
              #endregion
            }
            else
            {
              #region Save
              if (detail == null)
              {
                detail = new PurchaseDetail();
              }

              detail.Code = row["Code"] == DBNull.Value ? null : row["Code"].ToString().ToUpper();
              detail.PurchaseId = purchase.Id;
              detail.ProductId = Convert.ToInt32(row["ProductId"]);
              detail.Quantity = Convert.ToDouble(row["Quantity"]);
              detail.Price = row["Price"] == DBNull.Value ? 0 : Convert.ToInt32(row["Price"]);

              detailService.Save(detail);
              row["Id"] = detail.Id;
              #endregion
            }
          }
          #endregion

          ConnectionScope.Complete();
        }

        if (string.IsNullOrEmpty(customer.CustomerNo))
        {
          customer = cusService.GetById(customer.Id);
        }

        if (string.IsNullOrEmpty(purchase.RefNo))
        {
          purchase = purService.GetById(purchase.Id);
        }

        return string.Format("Save|{0}|{1}|{2}|{3}", customer.Id.ToString(), customer.CustomerNo, purchase.Id.ToString(), purchase.RefNo);
      }
      catch (Exception ex)
      {
        WriteLog("PurchaseInfo::Save", ex);
        return "Có lỗi trong quá trình lưu dữ liệu";
      }
    }

    private string Approve()
    {
      try
      {
        if (!CanModify)
        {
          return "Bạn không có quyền này";
        }

        int purchaseId = 0;
        Purchase purchase = null;
        if (int.TryParse(hfPurchaseId.Value, out purchaseId))
        {
          purchase = new PurchaseService().GetById(purchaseId);
        }

        if (purchase == null) return "Không tìm thấy thông tin tương ứng";
        new PurchaseService().Approve(purchase.Id);
        return "Approve|";
      }
      catch (Exception ex)
      {
        WriteLog("PurchaseInfo::Approve", ex);
        return "Có lỗi trong quá trình lưu dữ liệu";
      }
    }

    private string Reject()
    {
      try
      {
        if (!CanModify)
        {
          return "Bạn không có quyền này";
        }

        int purchaseId = 0;
        Purchase purchase = null;
        if (int.TryParse(hfPurchaseId.Value, out purchaseId))
        {
          purchase = new PurchaseService().GetById(purchaseId);
        }

        if (purchase == null) return "Không tìm thấy thông tin tương ứng";
        new PurchaseService().Reject(purchase.Id);
        return "Approve|";
      }
      catch (Exception ex)
      {
        WriteLog("PurchaseInfo::Reject", ex);
        return "Có lỗi trong quá trình lưu dữ liệu";
      }
    }
    #endregion
  }
}
